import java.util.List;
import java.util.Stack;

/*
 * @lc app=leetcode.cn id=145 lang=java
 *
 * [145] 二叉树的后序遍历
 *
 * https://leetcode-cn.com/problems/binary-tree-postorder-traversal/description/
 *
 * algorithms
 * Easy (75.28%)
 * Likes:    738
 * Dislikes: 0
 * Total Accepted:    348.2K
 * Total Submissions: 462.5K
 * Testcase Example:  '[1,null,2,3]'
 *
 * 给你一棵二叉树的根节点 root ，返回其节点值的 后序遍历 。
 * 
 * 
 * 
 * 示例 1：
 * 
 * 
 * 输入：root = [1,null,2,3]
 * 输出：[3,2,1]
 * 
 * 
 * 示例 2：
 * 
 * 
 * 输入：root = []
 * 输出：[]
 * 
 * 
 * 示例 3：
 * 
 * 
 * 输入：root = [1]
 * 输出：[1]
 * 
 * 
 * 
 * 
 * 提示：
 * 
 * 
 * 树中节点的数目在范围 [0, 100] 内
 * -100 <= Node.val <= 100
 * 
 * 
 * 
 * 
 * 进阶：递归算法很简单，你可以通过迭代算法完成吗？
 * 
 */

// @lc code=start
/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    
    // 递归
    // public List<Integer> postorderTraversal(TreeNode root) {
    //     List<Integer> arrayList = new ArrayList<>();
    //     if (root != null) {
    //         // 遍历左子树
    //         arrayList.addAll(postorderTraversal(root.left));
    //         // 遍历右子树
    //         arrayList.addAll(postorderTraversal(root.right));
    //         arrayList.add(root.val);
    //     }
    //     return arrayList;  
    // }

    // 迭代 (逆转前序遍历法)
    // public List<Integer> postorderTraversal(TreeNode root) {
    //     List<Integer> arrayList = new ArrayList<Integer>();
    //     Stack<TreeNode> stack = new Stack<>();
    //     TreeNode p = root;
    //     while (p != null || !stack.empty()) {
    //         if (p != null) {
    //             stack.push(p);
    //             // 右孩子入栈前
    //             arrayList.add(0, p.val);
    //             p = p.right;
    //         } else {
    //             TreeNode treeNode = stack.pop();
    //             p = treeNode.left; 
    //         }
    //     }
    //     return arrayList;
    // }

    // 迭代
    public List<Integer> postorderTraversal(TreeNode root) {
        List<Integer> arrayList = new ArrayList<Integer>();
        Stack<TreeNode> stack = new Stack<>();
        TreeNode p = root;
        // pre指向被添加到列表里的元素
        // 当父节点的右孩子是这个元素是，他可以被添加(左右父顺序)
        TreeNode pre = null;
        while (p != null || !stack.empty()) {
            while (p != null) {
                stack.push(p);
                p = p.left;
            }
            p = stack.pop();
            // 走到最底下的左孩子，此孩子（父）若没有右孩子则可以被添加(左右父顺序)
            if (p.right == null || p.right == pre) {
                arrayList.add(p.val);
                pre = p;
                p = null;
            } else {
                stack.push(p);
                p = p.right;
            }
        }
        return arrayList;
    }

}
// @lc code=end

